package net.sf.nlp.ltag.parser.dot;

import java.util.ArrayList;

import net.sf.nlp.ltag.data.LTAGNode;
import net.sf.nlp.ltag.data.LTAGTree;
import net.sf.nlp.ltag.parser.LTAGState;
import net.sf.nlp.ltag.parser.LeafNode;

public class DotState extends LTAGState {
	
	private ArrayList<LeafNode> scanedNodes = new ArrayList<LeafNode>();
		
	public DotState(LTAGTree tree)
	{
		super(tree);
	}

	public ArrayList<LeafNode> getScanedNodes() {
		return scanedNodes;
	}
	
	public void setScanedNodes(ArrayList<LeafNode> scanedNodes) {
		this.scanedNodes = scanedNodes;
	}

	public LeafNode getAndRemoveLastScanedNodes()
	{
		if (scanedNodes.size() == 0)
			return null;
		
		return scanedNodes.remove(scanedNodes.size() - 1);
	}
	
	public LeafNode getNextTreeNode()
	{
		LTAGTree nextTree = tree;
		LTAGNode nextNode = node;
		
		do 
		{
			int nextLocation = nextNode.getLocation() + 1;
			
			if (nextTree.getNodesCount() > nextLocation)
			{
				if (!recongizedNode(nextNode))
					return null;
				
				LeafNode nextLeafNode = new LeafNode(nextTree, nextTree.getNodeByLocation(nextLocation));
				return nextLeafNode;
			}
			
			LeafNode leafNode = getAndRemoveLastScanedNodes();
			
			if (leafNode == null)
				return null;
			
			if (!recongizedTree(nextTree))
				return null;
			
			nextTree = leafNode.getTree();
			nextNode = leafNode.getLeafNode();
			
		} while(true);
		
	}
	
	private boolean recongizedWord(int wordIndex)
	{
		if (parsedLeafNodes.size() <= wordIndex)
			return false;
		
		LeafNode leafNode = null;
		
		for (int i = 0; i <= wordIndex; i++)
		{
			leafNode = parsedLeafNodes.get(i);
			
			if (leafNode.getTree().getWordIndex() != i)
				return false;
		}
		
		return true;
	}
	
	private boolean recongizedTree(LTAGTree tree)
	{
		int lastNodeIndex = -1;
		LeafNode leafNode = null;
		
		for (int i = parsedLeafNodes.size() - 1; i >=0; i--)
		{
			leafNode = parsedLeafNodes.get(i);
			
			if (lastNodeIndex == -1 && leafNode.getTree() == tree)
				lastNodeIndex = i;
			
			if (lastNodeIndex == -1)
				continue;
			
			if (leafNode.getLeafNode().getWord() == null)
				return false;
			
			if (leafNode.getLeafNode().getWord().getWordIndex() != i)
				return false;
		}
		
		return true;
	}
	
	private boolean recongizedNode(LTAGNode node)
	{
		if (node.getChildren() != null && node.getChildren().size() > 0)
			return true;
		
		if ("*".equals(node.getType()))
			return recongizedTree(tree);
			
		if (node.getWord() == null)
			return true;
		
		return recongizedWord(node.getWord().getWordIndex());
	}
	
	public DotState clone()
	{
		DotState clone = null;
		
		clone = (DotState)super.clone();
		clone.setScanedNodes(cloneScanedNodes());
		
		return clone;
	}
	
	@SuppressWarnings("unchecked")
	public ArrayList<LeafNode> cloneScanedNodes()
	{
		return (ArrayList<LeafNode>)scanedNodes.clone();
	}
}
